﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using Experimentor.CheckResponsiveness;
using System.IO;
using System.Xml.Serialization;
using System.Reflection;
using IWshRuntimeLibrary;
using System.Xml;

namespace Experimentor
{
    public partial class Form_BuildExperim : Form
    {
        private List<Control> enableSwitchControls;
        private List<ToolStripMenuItem> enableSwitchToolStripMenuItems;

        private TextAndFileButtonControl textfbtnControl;
        private TextAndEditcodeButtonControl textecbtnControl;

        private String currentFile;
        private ExperimentDef currentDef;
        private bool fileChanged = false;

        private string copySlidename = null;
        private Sequence copySequence = null;

        public Form_BuildExperim()
        {
            InitializeComponent();
            //prepare list of controls that is enabled/disabled together
            this.enableSwitchToolStripMenuItems = new List<ToolStripMenuItem>();
            this.enableSwitchToolStripMenuItems.Add(this.toolStripMenuItem_Save);
            this.enableSwitchToolStripMenuItems.Add(this.toolStripMenuItem_SaveAs);
            this.enableSwitchToolStripMenuItems.Add(this.toolStripMenuItem_Close);
            this.enableSwitchToolStripMenuItems.Add(this.toolStripMenuItem_Preview);
            this.enableSwitchToolStripMenuItems.Add(this.toolStripMenuItem_CreateLink);

            this.enableSwitchControls = new List<Control>();
            this.enableSwitchControls.Add(this.label_Attributes);
            this.enableSwitchControls.Add(this.dataGridView_Attributes);
            this.enableSwitchControls.Add(this.label_SetsOfSlides);
            this.enableSwitchControls.Add(this.button_Slides_AddColumn);
            this.enableSwitchControls.Add(this.button_LoadSlides);
            this.enableSwitchControls.Add(this.dataGridView_Slides);
            this.enableSwitchControls.Add(this.label_Sequences);
            this.enableSwitchControls.Add(this.dataGridView_Sequences);
            this.enableSwitchControls.Add(this.label_Sequence);
            this.enableSwitchControls.Add(this.label_UserDefFunctions);
            this.enableSwitchControls.Add(this.dataGridView_UserdefFunctions);
            //prepare the datagridview for attributes
            this.dataGridView_Attributes.AutoGenerateColumns = false;
            DataGridViewTextBoxColumn dgv_atributes_column_Order = new DataGridViewTextBoxColumn();
            dgv_atributes_column_Order.HeaderText = "Order";
            dgv_atributes_column_Order.DataPropertyName = "Order";
            DataGridViewTextBoxColumn dgv_atributes_column_Varname = new DataGridViewTextBoxColumn();
            dgv_atributes_column_Varname.HeaderText = "Variable Name";
            dgv_atributes_column_Varname.DataPropertyName = "Varname";
            DataGridViewTextBoxColumn dgv_atributes_column_Text = new DataGridViewTextBoxColumn();
            dgv_atributes_column_Text.HeaderText = "Text";
            dgv_atributes_column_Text.DataPropertyName = "Text";
            DataGridViewCheckBoxColumn dgv_atributes_column_Mandatory = new DataGridViewCheckBoxColumn();
            dgv_atributes_column_Mandatory.HeaderText = "Is mandatory?";
            dgv_atributes_column_Mandatory.DataPropertyName = "Mandatory";
            DataGridViewComboBoxColumn dgv_atributes_column_Fieldtype = new DataGridViewComboBoxColumn();
            dgv_atributes_column_Fieldtype.HeaderText = "Fieldtype";
            dgv_atributes_column_Fieldtype.DataSource = Enum.GetValues(typeof(PAFieldtype));
            dgv_atributes_column_Fieldtype.DataPropertyName = "Fieldtype";
            DataGridViewTextBoxColumn dgv_atributes_column_Values = new DataGridViewTextBoxColumn();
            dgv_atributes_column_Values.HeaderText = "Values";
            dgv_atributes_column_Values.DataPropertyName = "Values";
            DataGridViewTextBoxColumn dgv_atributes_column_Style = new DataGridViewTextBoxColumn();
            dgv_atributes_column_Style.HeaderText = "Style";
            dgv_atributes_column_Style.DataPropertyName = "Style";
            this.dataGridView_Attributes.Columns.Add(dgv_atributes_column_Order);
            this.dataGridView_Attributes.Columns.Add(dgv_atributes_column_Varname);
            this.dataGridView_Attributes.Columns.Add(dgv_atributes_column_Text);
            this.dataGridView_Attributes.Columns.Add(dgv_atributes_column_Mandatory);
            this.dataGridView_Attributes.Columns.Add(dgv_atributes_column_Fieldtype);
            this.dataGridView_Attributes.Columns.Add(dgv_atributes_column_Values);
            this.dataGridView_Attributes.Columns.Add(dgv_atributes_column_Style);
            //prepare the datagridview for slides
            this.dataGridView_Slides.AutoGenerateColumns = false;
            this.dataGridView_Slides.CellBeginEdit += new DataGridViewCellCancelEventHandler(dataGridView_Slides_CellBeginEdit);
            this.dataGridView_Slides.CellEndEdit += new DataGridViewCellEventHandler(dataGridView_Slides_CellEndEdit);
            this.dataGridView_Slides.Scroll += new ScrollEventHandler(dataGridView_Slides_Scroll);
            //prepare the datagridview for sequences
            this.dataGridView_Sequences.AutoGenerateColumns = false;
            DataGridViewTextBoxColumn dgv_sequences_column_Order = new DataGridViewTextBoxColumn();
            dgv_sequences_column_Order.HeaderText = "Order";
            dgv_sequences_column_Order.DataPropertyName = "Order";
            DataGridViewTextBoxColumn dgv_sequences_column_Name = new DataGridViewTextBoxColumn();
            dgv_sequences_column_Name.Name = "Name";
            dgv_sequences_column_Name.HeaderText = "Name";
            dgv_sequences_column_Name.DataPropertyName = "Name";
            DataGridViewTextBoxColumn dgv_sequences_column_SheetName = new DataGridViewTextBoxColumn();
            dgv_sequences_column_SheetName.Name = "SheetName";
            dgv_sequences_column_SheetName.HeaderText = "Sheet name";
            dgv_sequences_column_SheetName.DataPropertyName = "SheetName";
            DataGridViewTextBoxColumn dgv_sequences_column_Fromset = new DataGridViewTextBoxColumn();
            dgv_sequences_column_Fromset.HeaderText = "From set";
            dgv_sequences_column_Fromset.DataPropertyName = "Fromset";
            DataGridViewTextBoxColumn dgv_sequences_column_Toset = new DataGridViewTextBoxColumn();
            dgv_sequences_column_Toset.HeaderText = "To set";
            dgv_sequences_column_Toset.DataPropertyName = "Toset";
            DataGridViewCheckBoxColumn dgv_sequences_column_Randomize = new DataGridViewCheckBoxColumn();
            dgv_sequences_column_Randomize.HeaderText = "Randomize";
            dgv_sequences_column_Randomize.DataPropertyName = "Randomize";
            DataGridViewComboBoxColumn dgv_sequences_column_SlideLayout = new DataGridViewComboBoxColumn();
            dgv_sequences_column_SlideLayout.HeaderText = "Layout";
            dgv_sequences_column_SlideLayout.DataPropertyName = "SlideLayout";
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            IEnumerable<Type> allSlideLayouts = currentAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof(SlideLayout)));
            DataTable slideLayoutNames = new DataTable("slideLayoutNames");
            slideLayoutNames.Columns.Add("Keys");
            slideLayoutNames.Columns.Add("Values");
            foreach (Type layoutType in allSlideLayouts)
            {
                SlideLayout layout = Activator.CreateInstance(layoutType) as SlideLayout;
                slideLayoutNames.Rows.Add(layoutType.Name, layout.Name);
            }
            dgv_sequences_column_SlideLayout.DataSource = slideLayoutNames;
            dgv_sequences_column_SlideLayout.DisplayMember = "Values";
            dgv_sequences_column_SlideLayout.ValueMember = "Keys";
            DataGridViewTextBoxColumn dgv_sequences_column_LayoutArgs = new DataGridViewTextBoxColumn();
            dgv_sequences_column_LayoutArgs.HeaderText = "Layout arguments";
            dgv_sequences_column_LayoutArgs.DataPropertyName = "LayoutArgs";
            DataGridViewTextBoxColumn dgv_sequences_column_Events = new DataGridViewTextBoxColumn();
            dgv_sequences_column_Events.HeaderText = "Events";
            dgv_sequences_column_Events.DataPropertyName = "Events";
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_Order);
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_Name);
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_SheetName);
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_Fromset);
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_Toset);
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_Randomize);
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_SlideLayout);
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_LayoutArgs);
            this.dataGridView_Sequences.Columns.Add(dgv_sequences_column_Events);
            //prepare the datagridview for user defined functions
            this.dataGridView_UserdefFunctions.AutoGenerateColumns = false;
            this.dataGridView_UserdefFunctions.CellBeginEdit += new DataGridViewCellCancelEventHandler(dataGridView_UserdefFunctions_CellBeginEdit);
            this.dataGridView_UserdefFunctions.CellEndEdit += new DataGridViewCellEventHandler(dataGridView_UserdefFunctions_CellEndEdit);
            this.dataGridView_UserdefFunctions.Scroll += new ScrollEventHandler(dataGridView_UserdefFunctions_Scroll);
            DataGridViewTextBoxColumn dgv_udeffunctions_column_Name = new DataGridViewTextBoxColumn();
            dgv_udeffunctions_column_Name.HeaderText = "Name";
            dgv_udeffunctions_column_Name.DataPropertyName = "Name";
            DataGridViewComboBoxColumn dgv_udeffunctions_column_Functiontype = new DataGridViewComboBoxColumn();
            dgv_udeffunctions_column_Functiontype.HeaderText = "Function Type";
            dgv_udeffunctions_column_Functiontype.DataPropertyName = "Functiontype";
            IEnumerable<Type> allFunctiontypes = currentAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof(UserdefFunctionType)));
            DataTable functionTypeNames = new DataTable("functionTypeNames");
            functionTypeNames.Columns.Add("Keys");
            functionTypeNames.Columns.Add("Values");
            foreach (Type functionType in allFunctiontypes)
            {
                UserdefFunctionType ftype = Activator.CreateInstance(functionType) as UserdefFunctionType;
                functionTypeNames.Rows.Add(functionType.Name, ftype.Name);
            }
            dgv_udeffunctions_column_Functiontype.DataSource = functionTypeNames;
            dgv_udeffunctions_column_Functiontype.DisplayMember = "Values";
            dgv_udeffunctions_column_Functiontype.ValueMember = "Keys";
            DataGridViewTextBoxColumn dgv_udeffunctions_column_Code = new DataGridViewTextBoxColumn();
            dgv_udeffunctions_column_Code.HeaderText = "Program code";
            dgv_udeffunctions_column_Code.Name = "Code";
            dgv_udeffunctions_column_Code.DataPropertyName = "Code";
            dgv_udeffunctions_column_Code.Width = 300;
            dgv_udeffunctions_column_Code.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            this.dataGridView_UserdefFunctions.Columns.Add(dgv_udeffunctions_column_Name);
            this.dataGridView_UserdefFunctions.Columns.Add(dgv_udeffunctions_column_Functiontype);
            this.dataGridView_UserdefFunctions.Columns.Add(dgv_udeffunctions_column_Code);
        }

        private void dataGridView_UserdefFunctions_Scroll(object sender, ScrollEventArgs e)
        {
            if (this.textecbtnControl.Visible == true)
            {
                Rectangle r = this.dataGridView_UserdefFunctions.GetCellDisplayRectangle(this.dataGridView_UserdefFunctions.CurrentCell.ColumnIndex, this.dataGridView_UserdefFunctions.CurrentCell.RowIndex, true);
                this.textecbtnControl.Location = r.Location;
                this.textecbtnControl.Size = r.Size;
            }
        }

        private void dataGridView_UserdefFunctions_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            if (this.dataGridView_UserdefFunctions.Columns[e.ColumnIndex].Name == "Code" && e.RowIndex > -1 && e.RowIndex != this.dataGridView_UserdefFunctions.NewRowIndex)
            {
                this.textecbtnControl.setUdeffunc(this.dataGridView_UserdefFunctions.CurrentRow.DataBoundItem as UserdefFunction);
                Rectangle rect = this.dataGridView_UserdefFunctions.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
                this.textecbtnControl.Location = rect.Location;
                this.textecbtnControl.Size = rect.Size;
                this.textecbtnControl.Text = this.dataGridView_UserdefFunctions.CurrentCell.Value.ToString();
                this.textecbtnControl.renderControl();
                this.textecbtnControl.Visible = true;
            }
        }

        private void dataGridView_Slides_Scroll(object sender, ScrollEventArgs e)
        {
            if (this.textfbtnControl.Visible == true)
            {
                Rectangle r = this.dataGridView_Slides.GetCellDisplayRectangle(this.dataGridView_Slides.CurrentCell.ColumnIndex,this.dataGridView_Slides.CurrentCell.RowIndex,true);
                this.textfbtnControl.Location = r.Location;
                this.textfbtnControl.Size = r.Size;
            }
        }

        private void dataGridView_Slides_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            if (e.ColumnIndex > 0 && e.RowIndex > -1 && e.RowIndex != this.dataGridView_Slides.NewRowIndex)
            {
                Rectangle rect = this.dataGridView_Slides.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
                this.textfbtnControl.Location = rect.Location;
                this.textfbtnControl.Size = rect.Size;
                this.textfbtnControl.Text = this.dataGridView_Slides.CurrentCell.Value.ToString();
                this.textfbtnControl.renderControl();
                this.textfbtnControl.Visible = true;
            }
        }

        public Form_BuildExperim(string filename)
            : this()
        {
            if (System.IO.File.Exists(filename))
            {
                this.currentFile = filename;
                this.currentDef = new ExperimentDef();
                FileStream fs = new FileStream(this.currentFile, FileMode.Open);
                XmlSerializer xmls = new XmlSerializer(this.currentDef.GetType());
                this.currentDef = (ExperimentDef)(xmls.Deserialize(fs));
                fs.Close();
                this.resetFields();
                this.fileChanged = false;
                this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile);
            }
        }

        private void toolStripMenuItem_CheckResponsiveness_Click(object sender, EventArgs e)
        {
            form_CheckResponsiveness form_CR = new form_CheckResponsiveness();
            form_CR.ShowDialog(this);
        }

        private void toolStripMenuItem_New_Click(object sender, EventArgs e)
        {
            if (this.fileChanged)
            {
                DialogResult dr = MessageBox.Show("Do you want to save?", "Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (dr == DialogResult.Cancel) return;
                else if (dr == DialogResult.Yes) this.toolStripMenuItem_Save_Click(sender, e);
            }
            this.currentFile = null;
            this.currentDef = new ExperimentDef();
            this.fileChanged = true;
            this.Text = "Experimentor - Build Experiment - [new]*";
            this.resetFields();
            this.attachFileAndButtonTextfields();
        }

        private void attachFileAndButtonTextfields()
        {
            if (this.textfbtnControl != null) this.dataGridView_Slides.Controls.Remove(this.textfbtnControl);
            if (this.currentFile != null) this.textfbtnControl = new TextAndFileButtonControl(new Uri(this.currentFile, UriKind.Absolute));
            else this.textfbtnControl = new TextAndFileButtonControl(null);
            this.textfbtnControl.Visible = false;
            this.dataGridView_Slides.Controls.Add(this.textfbtnControl);

            if (this.textecbtnControl != null) this.dataGridView_Slides.Controls.Remove(this.textecbtnControl);
            this.textecbtnControl = new TextAndEditcodeButtonControl();
            this.textecbtnControl.Visible = false;
            this.dataGridView_UserdefFunctions.Controls.Add(this.textecbtnControl);
        }

        private void resetFields()
        {
            if (this.currentDef != null)
            {
                //bind the datagridview for attributes
                this.dataGridView_Attributes.DataSource = this.currentDef.personAttributes;
                this.dataGridView_Attributes.AutoResizeColumns();
                this.dataGridView_Attributes.Visible = true;
                //bind the datagridview for slides
                this.dataGridView_Slides.Columns.Clear();
                this.dataGridView_Slides.DataSource = this.currentDef.slides;
                DataGridViewTextBoxColumn ordercolumn = new DataGridViewTextBoxColumn();
                ordercolumn.Name = "Order";
                ordercolumn.HeaderText = "Order";
                ordercolumn.DataPropertyName = "Order";
                this.dataGridView_Slides.Columns.Add(ordercolumn);
                foreach (DataColumn column in this.currentDef.slides.Columns)
                {
                    if (column.ColumnName == "Order") continue;
                    DataGridViewTextBoxColumn newcolumn = new DataGridViewTextBoxColumn();
                    newcolumn.Name = column.ColumnName;
                    newcolumn.HeaderText = column.ColumnName;
                    newcolumn.DataPropertyName = column.ColumnName;
                    newcolumn.MinimumWidth = 100;
                    this.dataGridView_Slides.Columns.Add(newcolumn);
                }
                foreach (DataGridViewColumn column in this.dataGridView_Slides.Columns) column.SortMode = DataGridViewColumnSortMode.NotSortable;
                this.dataGridView_Slides.Columns["Order"].ReadOnly = true;
                this.dataGridView_Slides.Columns["Order"].HeaderCell.Style.Font = new Font(this.dataGridView_Slides.DefaultCellStyle.Font, FontStyle.Italic);
                this.dataGridView_Slides.Columns["Order"].DefaultCellStyle.Font = new Font(this.dataGridView_Slides.DefaultCellStyle.Font, FontStyle.Italic);
                this.dataGridView_Slides.AutoResizeColumns();
                this.dataGridView_Slides.Visible = true;
                //bind the datagridview for sequences
                this.dataGridView_Sequences.DataSource = this.currentDef.sequences;
                this.dataGridView_Sequences.AutoResizeColumns();
                this.dataGridView_Sequences.Visible = true;
                //bind the datagridview for user defined functions
                this.dataGridView_UserdefFunctions.DataSource = this.currentDef.userdefFunctions;
                this.dataGridView_UserdefFunctions.AutoResizeColumns();
                this.dataGridView_UserdefFunctions.Visible = true;
                //enable controls
                this.enableControls(true);
            }
            else
            {
                this.dataGridView_Attributes.Visible = false;
                this.dataGridView_Attributes.DataSource = null;
                this.dataGridView_Slides.Visible = false;
                this.dataGridView_Slides.DataSource = null;
                this.dataGridView_Sequences.Visible = false;
                this.dataGridView_Sequences.DataSource = null;
                this.dataGridView_SeqDef.Visible = false;
                this.dataGridView_SeqDef.DataSource = null;
                this.dataGridView_SeqDef.Columns.Clear();
                this.dataGridView_SeqDef.Enabled = false;
                this.dataGridView_UserdefFunctions.Visible = false;
                this.dataGridView_UserdefFunctions.DataSource = null;
                this.enableControls(false);
            }
        }

        private void enableControls(bool enable)
        {
            foreach (ToolStripMenuItem item in this.enableSwitchToolStripMenuItems) item.Enabled = enable;
            foreach (Control control in this.enableSwitchControls) control.Enabled = enable;
        }

        private void toolStripMenuItem_Save_Click(object sender, EventArgs e)
        {
            if (this.currentFile == null) this.toolStripMenuItem_SaveAs_Click(sender, e);
            else
            {
                this.saveFields();
                this.fileChanged = false;
                this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile);
            }
        }

        private void toolStripMenuItem_SaveAs_Click(object sender, EventArgs e)
        {
            SaveFileDialog fd = new SaveFileDialog();
            fd.Filter = "Experimentor|*.exp";
            fd.AddExtension = true;
            fd.DefaultExt = "exp";
            DialogResult dr = fd.ShowDialog(this);
            if (dr != DialogResult.OK) return;
            else
            {
                this.currentFile = fd.FileName;
                this.saveFields();
                this.attachFileAndButtonTextfields();
                this.fileChanged = false;
                this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile);
            }
        }

        private void saveFields()
        {
            XmlWriterSettings ws = new XmlWriterSettings();
            ws.NewLineHandling = NewLineHandling.Entitize;
            XmlSerializer xmls = new XmlSerializer(this.currentDef.GetType());
            using (XmlWriter wr = XmlWriter.Create(this.currentFile, ws))
            {
                xmls.Serialize(wr, this.currentDef);
            }
        }

        private void toolStripMenuItem_Open_Click(object sender, EventArgs e)
        {
            DialogResult dr;
            if (this.fileChanged)
            {
                dr = MessageBox.Show("Do you want to save?", "Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (dr == DialogResult.Cancel) return;
                else if (dr == DialogResult.Yes)
                {
                    this.toolStripMenuItem_Save_Click(sender, e);
                    this.fileChanged = false;
                    this.toolStripMenuItem_Close_Click(sender, e);
                }
                else if (dr == DialogResult.No)
                {
                    this.fileChanged = false;
                    this.toolStripMenuItem_Close_Click(sender, e);
                }
            }
            OpenFileDialog fd = new OpenFileDialog();
            fd.Filter = "Experimentor|*.exp|All files|*.*";
            fd.Multiselect = false;
            dr = fd.ShowDialog(this);
            if (dr != DialogResult.OK) return;
            else
            {
                this.currentFile = fd.FileName;
                this.currentDef = new ExperimentDef();
                FileStream fs = new FileStream(this.currentFile, FileMode.Open);
                XmlSerializer xmls = new XmlSerializer(this.currentDef.GetType());
                try
                {
                    this.currentDef = (ExperimentDef)(xmls.Deserialize(fs));
                    //add handler to data structures
                    this.currentDef.SetHandler();
                    this.resetFields();
                    this.attachFileAndButtonTextfields();
                    this.fileChanged = false;
                    this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile);
                }
                catch (InvalidOperationException ioe)
                {
                    this.currentFile = null;
                    this.currentDef = null;
                    MessageBox.Show("Cannot open file: " + ioe.InnerException.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                fs.Close();
            }
        }

        private void Form_BuildExperim_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.fileChanged)
            {
                DialogResult dr = MessageBox.Show("Do you want to save?", "Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (dr == DialogResult.Cancel) e.Cancel = true;
                else if (dr == DialogResult.Yes) this.toolStripMenuItem_Save_Click(sender, e);
            }
        }

        private void toolStripMenuItem_Exit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void dataGridView_Attributes_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (this.currentFile != null) this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile) + "*";
            else this.Text = "Experimentor - Build Experiment - [new]*";
            this.fileChanged = true;
        }

        private void toolStripMenuItem_Close_Click(object sender, EventArgs e)
        {
            if (this.currentDef == null) return;
            if (this.fileChanged)
            {
                DialogResult dr = MessageBox.Show("Do you want to save?", "Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (dr == DialogResult.Cancel) return;
                else if (dr == DialogResult.Yes) this.toolStripMenuItem_Save_Click(sender, e);
            }
            this.currentFile = null;
            this.currentDef = null;
            this.fileChanged = false;
            this.Text = "Experimentor - Build Experiment";
            this.resetFields();
        }

        private void button_Slides_AddColumn_Click(object sender, EventArgs e)
        {
            this.currentDef.slides_do_addColumn();
            DataGridViewTextBoxColumn newcolumn = new DataGridViewTextBoxColumn();
            newcolumn.HeaderText = this.currentDef.slides.Columns[this.currentDef.slides.Columns.Count - 1].ColumnName;
            newcolumn.Name = this.currentDef.slides.Columns[this.currentDef.slides.Columns.Count - 1].ColumnName;
            newcolumn.DataPropertyName = this.currentDef.slides.Columns[this.currentDef.slides.Columns.Count - 1].ColumnName;
            newcolumn.MinimumWidth = 100;
            this.dataGridView_Slides.Columns.Add(newcolumn);
            if (this.currentFile != null) this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile) + "*";
            else this.Text = "Experimentor - Build Experiment - [new]*";
            this.fileChanged = true;
        }

        private void dataGridView_Slides_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (this.currentFile != null) this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile) + "*";
            else this.Text = "Experimentor - Build Experiment - [new]*";
            this.fileChanged = true;
            if (e.ColumnIndex > 0 && e.RowIndex > -1 && e.RowIndex != this.dataGridView_Slides.NewRowIndex)
            {
                this.dataGridView_Slides.CurrentCell.Value = this.textfbtnControl.Text;
                this.textfbtnControl.Visible = false;
                this.dataGridView_Slides_CellValueChanged(sender, e);
            }
        }

        private void dataGridView_Slides_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex==0) return;
            string filename = this.dataGridView_Slides[e.ColumnIndex,e.RowIndex].Value as string;
            if (filename == null || filename.Length == 0) this.dataGridView_Slides[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.Black;
            else
            {
                string fullName;
                if (this.currentFile != null) fullName = Path.Combine(Path.GetDirectoryName(this.currentFile), filename);
                else fullName = filename;
                if (!System.IO.File.Exists(fullName)) this.dataGridView_Slides[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.Red;
                else this.dataGridView_Slides[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.Black;
            }
        }

        private void dataGridView_Sequences_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (this.currentFile != null) this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile) + "*";
            else this.Text = "Experimentor - Build Experiment - [new]*";
            this.fileChanged = true;
        }

        private void dataGridView_Sequences_SelectionChanged(object sender, EventArgs e)
        {
            DataGridViewSelectedRowCollection selRows = ((DataGridView)sender).SelectedRows;
            if (selRows==null || selRows.Count==0 || selRows[0].Index == this.dataGridView_Sequences.NewRowIndex)
            {
                this.label_Sequence.Text = "No sequence selected";
                this.dataGridView_SeqDef.Visible = false;
                this.dataGridView_SeqDef.DataSource = null;
                this.dataGridView_SeqDef.Columns.Clear();
                this.dataGridView_SeqDef.Enabled = false;                
            }
            else
            {
                this.label_Sequence.Text = "Sequence '" + selRows[0].Cells["Name"].Value + "':";
                this.dataGridView_SeqDef.AutoGenerateColumns = false;
                this.dataGridView_SeqDef.Columns.Clear();
                DataGridViewTextBoxColumn dgv_seqdef_column_Order = new DataGridViewTextBoxColumn();
                dgv_seqdef_column_Order.HeaderText = "Order";
                dgv_seqdef_column_Order.DataPropertyName = "Order";
                DataGridViewComboBoxColumn dgv_seqdef_column_Slide = new DataGridViewComboBoxColumn();
                dgv_seqdef_column_Slide.HeaderText = "Slide(s)";
                dgv_seqdef_column_Slide.DataPropertyName = "Slide";
                DataTable slideNames = new DataTable("slideNames");
                slideNames.Columns.Add("Keys",typeof(int));
                slideNames.Columns.Add("Values");
                //FIXME should be order-save
                foreach (DataGridViewColumn column in this.dataGridView_Slides.Columns)
                {
                    if (column.Name != "Order") slideNames.Rows.Add(column.Index-1,column.HeaderText);
                }
                
                dgv_seqdef_column_Slide.DataSource = slideNames;
                dgv_seqdef_column_Slide.DisplayMember = "Values";
                dgv_seqdef_column_Slide.ValueMember = "Keys";
                DataGridViewComboBoxColumn dgv_seqdef_column_Position = new DataGridViewComboBoxColumn();
                dgv_seqdef_column_Position.HeaderText = "Position";
                dgv_seqdef_column_Position.DataPropertyName = "Position";
                List<SlidePosition> slidePositions = this.currentDef.sequences[selRows[0].Index].getLayout().Positions;
                DataTable dt_slidePositions = new DataTable("slidePositions");
                dt_slidePositions.Columns.Add("Keys", typeof(int));
                dt_slidePositions.Columns.Add("Values");
                for (int i = 0; i < slidePositions.Count; i++) dt_slidePositions.Rows.Add(i, slidePositions[i].name);
                dgv_seqdef_column_Position.DataSource = dt_slidePositions;
                dgv_seqdef_column_Position.DisplayMember = "Values";
                dgv_seqdef_column_Position.ValueMember = "Keys";
                DataGridViewTextBoxColumn dgv_seqdef_column_Probability = new DataGridViewTextBoxColumn();
                dgv_seqdef_column_Probability.HeaderText = "Probability";
                dgv_seqdef_column_Probability.DataPropertyName = "Probability";
                DataGridViewTextBoxColumn dgv_seqdef_column_ShowMin = new DataGridViewTextBoxColumn();
                dgv_seqdef_column_ShowMin.HeaderText = "Show Min ms";
                dgv_seqdef_column_ShowMin.DataPropertyName = "ShowMin";
                DataGridViewTextBoxColumn dgv_seqdef_column_ShowMax = new DataGridViewTextBoxColumn();
                dgv_seqdef_column_ShowMax.HeaderText = "Show max ms";
                dgv_seqdef_column_ShowMax.DataPropertyName = "ShowMax";
                DataGridViewTextBoxColumn dgv_seqdef_column_ShowStep = new DataGridViewTextBoxColumn();
                dgv_seqdef_column_ShowStep.HeaderText = "Show steps ms";
                dgv_seqdef_column_ShowStep.DataPropertyName = "ShowStep";
                DataGridViewCheckBoxColumn dgv_seqdef_column_ShowBalanced = new DataGridViewCheckBoxColumn();
                dgv_seqdef_column_ShowBalanced.HeaderText = "Time balanced";
                dgv_seqdef_column_ShowBalanced.DataPropertyName = "ShowBalanced";
                DataGridViewComboBoxColumn dgv_seqdef_column_UserAction = new DataGridViewComboBoxColumn();
                dgv_seqdef_column_UserAction.HeaderText = "User action";
                dgv_seqdef_column_UserAction.DataPropertyName = "UserAction";
                Assembly currentAssembly = Assembly.GetExecutingAssembly();
                IEnumerable<Type> allUserActions = currentAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof(UserAction)));
                DataTable userActionNames = new DataTable("userActionNames");
                userActionNames.Columns.Add("Keys");
                userActionNames.Columns.Add("Values");
                foreach (Type userActionType in allUserActions)
                {
                    UserAction userAction = Activator.CreateInstance(userActionType) as UserAction;
                    userActionNames.Rows.Add(userActionType.Name, userAction.Name);
                }
                dgv_seqdef_column_UserAction.DataSource = userActionNames;
                dgv_seqdef_column_UserAction.DisplayMember = "Values";
                dgv_seqdef_column_UserAction.ValueMember = "Keys";
                DataGridViewTextBoxColumn dgv_seqdef_column_UserActionArgs = new DataGridViewTextBoxColumn();
                dgv_seqdef_column_UserActionArgs.HeaderText = "User action arguments";
                dgv_seqdef_column_UserActionArgs.DataPropertyName = "UserActionArgs";
                DataGridViewCheckBoxColumn dgv_seqdef_column_Save = new DataGridViewCheckBoxColumn();
                dgv_seqdef_column_Save.HeaderText = "Save";
                dgv_seqdef_column_Save.DataPropertyName = "Save";
                DataGridViewTextBoxColumn dgv_seqdef_column_Events = new DataGridViewTextBoxColumn();
                dgv_seqdef_column_Events.HeaderText = "Events";
                dgv_seqdef_column_Events.DataPropertyName = "Events";
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_Order);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_Slide);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_Position);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_Probability);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_ShowMin);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_ShowMax);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_ShowStep);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_ShowBalanced);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_UserAction);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_UserActionArgs);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_Save);
                this.dataGridView_SeqDef.Columns.Add(dgv_seqdef_column_Events);
                //FIXME unsave when sorting???
                this.dataGridView_SeqDef.DataSource = this.currentDef.sequences[selRows[0].Index].Parts;
                this.dataGridView_SeqDef.AutoResizeColumns();
                this.dataGridView_SeqDef.Visible = true;
                this.dataGridView_SeqDef.Enabled = true;
            }
        }

        private void dataGridView_SeqDef_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (this.currentFile != null) this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile) + "*";
            else this.Text = "Experimentor - Build Experiment - [new]*";
            this.fileChanged = true;
        }

        private void toolStripMenuItem_Preview_Click(object sender, EventArgs e)
        {
            this.toolStripMenuItem_Save_Click(sender, e);
            if (this.currentFile != null && this.currentFile.Length > 0)
            {
                form_ExperimRun formRun = new form_ExperimRun(true, this.currentFile);
                formRun.ShowDialog(this);
            }
        }

        private void toolStripMenuItem_CreateLink_Click(object sender, EventArgs e)
        {
            if (this.currentFile == null || this.currentFile.Length == 0) this.toolStripMenuItem_Save_Click(sender, e);
            if (this.currentFile != null && this.currentFile.Length > 0)
            {
                FolderBrowserDialog fd = new FolderBrowserDialog();
                fd.ShowNewFolderButton = true;
                fd.RootFolder = Environment.SpecialFolder.Desktop;
                fd.Description = "Select a folder for the link ...";
                DialogResult dr = fd.ShowDialog(this);
                if (dr == DialogResult.OK)
                {
                    object shDesktop = (object)"Desktop";
                    WshShell shell = new WshShell();
                    string shortcutAddress = fd.SelectedPath + @"\Experimentor - " + Path.GetFileNameWithoutExtension(this.currentFile) + ".lnk";
                    IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutAddress);
                    shortcut.Description = "Experimentor - " + Path.GetFileNameWithoutExtension(this.currentFile);
                    shortcut.TargetPath = Application.ExecutablePath;
                    shortcut.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath);
                    shortcut.Arguments = " -run \"" + this.currentFile + "\"";
                    shortcut.Save();
                }
            }
        }

        private void button_LoadSlides_Click(object sender, EventArgs e)
        {
            form_LoadSlides fls = new form_LoadSlides(this.currentFile, this.dataGridView_Slides.Columns);
            DialogResult dr = fls.ShowDialog(this);
            if (dr == DialogResult.OK)
            {
                int fromset;
                if (!int.TryParse(fls.textBox_FromSet.Text,out fromset) || fromset<1)
                {
                    MessageBox.Show(this,"Invalid number of set to start from.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
                    return;
                }
                int toset=0;
                int.TryParse(fls.textBox_ToSet.Text, out toset);
                int intoslide = (int)(fls.comboBox_Slide.SelectedValue);
                bool repeatedly = fls.checkBox_Repeat.Checked;
                if (fls.listBox_Files.Items.Count == 0) return;
                //if toset is smaller than fromset just insert all of the filenames
                if (toset<fromset)
                {
                    foreach (string filename in fls.listBox_Files.Items)
                    {
                        while (this.currentDef.slides.Rows.Count < fromset) this.currentDef.slides.Rows.Add(this.currentDef.slides.NewRow());
                        this.currentDef.slides.Rows[fromset - 1][intoslide] = filename;
                        fromset++;
                    }
                }
                //else insert as long as either the toset has been reached or there are no more filenames when not repeating
                else
                {
                    int i = 0;
                    while (fromset<=toset)
                    {
                        while (this.currentDef.slides.Rows.Count < fromset) this.currentDef.slides.Rows.Add(this.currentDef.slides.NewRow());
                        this.currentDef.slides.Rows[fromset - 1][intoslide] = (string)fls.listBox_Files.Items[i];
                        fromset++;
                        i++;
                        if (i == fls.listBox_Files.Items.Count)
                        {
                            if (repeatedly) i = 0;
                            else break;
                        }
                    }
                }
            }
        }

        private void dataGridView_Slides_KeyDown(object sender, KeyEventArgs e)
        {
            DataGridView dgv_sender = sender as DataGridView;
            if (!dgv_sender.IsCurrentCellInEditMode)
            {
                if (e.KeyCode == Keys.Delete) dgv_sender.CurrentCell.Value = "";
                else if (e.Control && e.KeyCode == Keys.X)
                {
                    this.copySlidename = dgv_sender.CurrentCell.Value as string;
                    dgv_sender.CurrentCell.Value = "";
                }
                else if (e.Control && e.KeyCode == Keys.C) this.copySlidename = dgv_sender.CurrentCell.Value as string;
                else if (e.Control && e.KeyCode == Keys.V) dgv_sender.CurrentCell.Value = this.copySlidename;
            }
        }

        private void dataGridView_UserdefFunctions_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (this.currentFile != null) this.Text = "Experimentor - Build Experiment - " + Path.GetFileNameWithoutExtension(this.currentFile) + "*";
            else this.Text = "Experimentor - Build Experiment - [new]*";
            this.fileChanged = true;
            if (this.dataGridView_UserdefFunctions.Columns[e.ColumnIndex].Name == "Code" && e.RowIndex > -1 && e.RowIndex != this.dataGridView_UserdefFunctions.NewRowIndex)
            {
                this.dataGridView_UserdefFunctions.CurrentCell.Value = this.textecbtnControl.Text;
                this.textecbtnControl.Visible = false;
            }
        }

        private void dataGridView_Sequences_KeyDown(object sender, KeyEventArgs e)
        {
            DataGridView dgv_sender = sender as DataGridView;
            if (!dgv_sender.IsCurrentCellInEditMode && dgv_sender.SelectedRows.Count==1)
            {
                if (e.Control && e.KeyCode == Keys.C)
                {
                    Sequence seq = dgv_sender.SelectedRows[0].DataBoundItem as Sequence;
                    this.copySequence = (Sequence)seq.Clone();
                }
                else if (e.Control && e.KeyCode == Keys.V && dgv_sender.SelectedRows[0].IsNewRow && this.copySequence!=null)
                {
                    dgv_sender.CancelEdit();
                    this.currentDef.sequences.Add(this.copySequence);
                    dgv_sender.Invalidate();
                    this.copySequence = null;
                }
            }
        }


    }

    class TextAndFileButtonControl : UserControl
    {
        private TextBox _textbox;
        private Button _button;
        private Uri _mainpath;

        public TextAndFileButtonControl(Uri mainpath)
        {
            this._mainpath = mainpath;
            this._textbox = new TextBox();
            this.Controls.Add(this._textbox);
            this._button = new Button();
            this._button.Text = "...";
            this.Controls.Add(this._button);
            this.renderControl();
            this._button.Click += new EventHandler(_button_Click);
        }

        void _button_Click(object sender, EventArgs e)
        {
            OpenFileDialog fd = new OpenFileDialog();
            if (this.Text != null && this.Text.Length > 0)
            {
                try
                {
                    fd.InitialDirectory = Path.GetDirectoryName(this.Text);
                }
                catch (Exception ex) { }
            }
            fd.Filter = "JPEG file|*.jpg;*.jpeg|All files|*.*";
            fd.Multiselect = false;
            DialogResult dr = fd.ShowDialog(((Control)sender).FindForm());
            if (dr == DialogResult.OK)
            {
                if (this._mainpath != null) this.Text = Uri.UnescapeDataString(this._mainpath.MakeRelativeUri(new Uri(fd.FileName, UriKind.Absolute)).ToString());
                else this.Text = fd.FileName;
            }
        }

        public override string Text
        {
            get { return this._textbox.Text; }
            set { this._textbox.Text = value; }
        }

        public void renderControl()
        {

            this._textbox.Location = new Point(0, 0);
            this._textbox.Width = this.Width-30;
            this._textbox.Height = this.Height;
            this._button.Location = new Point(this.Width - 30, 0);
            this._button.Width = 30;
            this._button.Height = this.Height;
        }

    }

    class TextAndEditcodeButtonControl : UserControl
    {
        private TextBox _textbox;
        private Button _button;
        private UserdefFunction _udeffunc;

        public TextAndEditcodeButtonControl()
        {
            this._textbox = new TextBox();
            this._textbox.Enabled = false;
            this.Controls.Add(this._textbox);
            this._button = new Button();
            this._button.Text = "...";
            this.Controls.Add(this._button);
            this.renderControl();
            this._button.Click += new EventHandler(_button_Click);
        }

        void _button_Click(object sender, EventArgs e)
        {
            form_EditCode fec = new form_EditCode(this._udeffunc);
            DialogResult dr = fec.ShowDialog(((Control)sender).FindForm());
            if (dr == DialogResult.OK) this.Text = fec.getCode();
        }

        public void setUdeffunc(UserdefFunction func)
        {
            this._udeffunc = func;
        }

        public override string Text
        {
            get { return this._textbox.Text; }
            set { this._textbox.Text = value; }
        }

        public void renderControl()
        {

            this._textbox.Location = new Point(0, 0);
            this._textbox.Width = this.Width - 30;
            this._textbox.Height = this.Height;
            this._button.Location = new Point(this.Width - 30, 0);
            this._button.Width = 30;
            this._button.Height = this.Height;
        }

    }
}
